package com.wang.spring;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.cglib.proxy.MethodProxy;

/*
在Spring AOP中，有 4 种类型通知(advices)的支持：
通知(Advice)之前 - 该方法执行前运行
通知(Advice)返回之后 – 运行后，该方法返回一个结果
异常通知，抛出异常后执行
环绕通知 – 环绕方法执行运行，结合以上这三个通知。
 
通知、增强处理（Advice）
连接点（JoinPoint） 方法有关的前前后后都是连接点
切入点（Pointcut） 切点来筛选连接点，选中那几个你想要的方法。
切面（Aspect）切面是通知和切入点的结合

aop正则匹配
其中execution 是用的最多的,其格式为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
执行（修饰符	返回类型	类型名？	方法名字（方法参数）	异常 ）
ret-type-pattern,name-pattern, and parameters-pattern是必须的.

ret-type-pattern:可以为*表示任何返回值,全路径的类名等.
name-pattern:指定方法名,*代表所以,set*,代表以set开头的所有方法.
parameters-pattern:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数,(*,String)代表第一个参数为任何值,第二个为String类型.

举例说明:
任意公共方法的执行：
execution(public * *(..))

任何一个以“set”开始的方法的执行：
execution(* set*(..))

AccountService 接口的任意方法的执行：
execution(* AccountService.*(..))

定义在service包里的任意方法的执行：
execution(* com.wang.service.*.*(..))

定义在service包和所有子包里的任意类的任意方法的执行：
execution(* com.wang.service..*.*(..))

定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行：
execution(* com.wang.pointcutexp..JoinPointObjP2.*(..))


 */

public class AopUtil implements MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor,ThrowsAdvice{

	@Override
	public void before(Method paramMethod, Object[] paramArrayOfObject, Object paramObject) throws Throwable {
		  System.out.println("Method before is invoked!");
	}

	@Override
	public void afterReturning(Object paramObject1, Method paramMethod, Object[] paramArrayOfObject,
			Object paramObject2) throws Throwable {
		  System.out.println("after Returning is invoked!");
	}


	@Override
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//		System.out.println("Method name : "
//				+ methodInvocation.getMethod().getName());
//		System.out.println("Method arguments : "
//				+ Arrays.toString(methodInvocation.getArguments()));
				
		System.out.println("method around id invoked");
		Object result = methodInvocation.proceed();
		System.out.println("after around invoked! "+ result);
		return result;
	}
	
	public void afterThrowing(IllegalArgumentException e) throws Throwable {
		System.out.println("afterThrowing is invoked! "+e);
	}
		
	
}
